package cn.agiledata.bank.transaction.action;

import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import cn.agiledata.bank.common.dao.AccountTemplateInter;
import cn.agiledata.bank.common.dao.ActionTypeTemplate;
import cn.agiledata.bank.common.dao.TransactionTemplate;
import cn.agiledata.bank.common.service.ICommonService;
import cn.agiledata.bank.common.service.PermissionService;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.ForeDict;
import cn.agiledata.bank.common.util.WeatherUtil;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.ActionType;
import cn.agiledata.bank.hibernateBean.SubAccount;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.myspace.service.IMySpaceService;
import cn.agiledata.bank.transaction.exception.TransactionException;
import cn.agiledata.bank.transaction.form.InpourForm;
import cn.agiledata.bank.transaction.service.FeeRatioInterf;
import com.vnv.infrastructure.action.IPBBaseAction;
import com.vnv.infrastructure.logic.IPBAppFactory;
import com.vnv.infrastructure.logic.IPBMgrFactory;

/**
 * 充值
 * 
 * @author maxianbo
 * 
 */
public abstract class InpourAction extends IPBBaseAction {
    /**
     * 分发调度
     */
    public abstract ActionForward assign(ActionMapping mapping,
            ActionForm actionForm, HttpServletRequest request,
            HttpServletResponse response) throws Exception;

    /**
     * 进行充值操作
     */
    public abstract ActionForward inpour(ActionMapping mapping,
            ActionForm actionForm, HttpServletRequest request,
            HttpServletResponse response) throws Exception;

    /**
     * 填写充值信息
     */
    public ActionForward fill(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        InpourForm form = (InpourForm) actionForm;
        try {
            // 判断当前用户是否具有充值权限
            PermissionService permissionService = PermissionService
                    .getPermissionService();
            if (!permissionService.hasPermission(request,
                    Constant.PERMIS_TYPE_BANKDEPOSIT)) {
                throw TransactionException.NO_PERMISSION;
            }

            String subAccountId = form.getSubAccountId();
            Double amount = validateAmount(form.getAmount());
            ActionType actionType = getActionType(form.getActionType());
            SubAccount subAccount = getAccountTemplate()
                    .getSubAccountBySubAccountId(subAccountId);
            request.setAttribute("subAccount", subAccount);
            String actionTypeId = actionType.getId().toString();
            // 获取费率
            double creditFee = getFeeRatioService().getCreditFee(null,
                    subAccount.getAccount(), actionTypeId, amount);
            request.setAttribute("fee", new Double(creditFee));
            // 如果费率内扣且充值金额低于费率
            if (getCommonService().compareAmounts(
                    subAccount.getId().toString(), actionTypeId, amount) != 0) {
                // 生成充值金额低于费率的异常
                throw TransactionException.getAmountUnderFeeException(amount
                        .doubleValue(), creditFee);
            }
        } catch (TransactionException e) {
            // 处理业务逻辑异常
            handleAppException(mapping, actionForm, request, response, e);
            // 跳转到第1步，之前重新装载子账户列表
            loadSubAccountList(request);
            // 设置为上一步的步骤序数，防止序数与步骤不同步
            form.setPreviousStep();
            return mapping.findForward(ForeDict.FORWARD_STEP_1);
        }
        loadIsCorpAccount(request);

        saveToken(request);
        return mapping.findForward(ForeDict.FORWARD_STEP_2);
    }

    /**
     * 判断是否企业用户
     */
    private void loadIsCorpAccount(HttpServletRequest request) {
        Boolean corpAccount = new Boolean(isCorpAccount(request));
        request.setAttribute("corpAccount", corpAccount);
    }

    /**
     * 
     * @return 交易类型代码
     */
    protected abstract String getActionTypeCode(HttpServletRequest request);

    /**
     * 交易类型值获取交易类型对象
     */
    protected final ActionType getActionType(String actionTypeCode) {
        return getActionTypeTemplate().getActionTypeByActionId(actionTypeCode);
    }

    protected final AccountTemplateInter getAccountTemplate() {
        return (AccountTemplateInter) IPBAppFactory
                .getObj(ForeDict.ACCOUNT_TEMPLATE);
    }

    protected final ActionTypeTemplate getActionTypeTemplate() {
        return (ActionTypeTemplate) IPBAppFactory
                .getObj(ForeDict.ACTION_TYPE_TEMPLATE);
    }

    protected final ICommonService getCommonService() {
        return (ICommonService) IPBAppFactory.getObj(ForeDict.SERVICE_COMMON);
    }

    /**
     * 获取当前账户
     */
    protected final Account getCurrentAccount(HttpServletRequest request) {
        long accountId = WeatherUtil.getAccountIdFromSession(request);
        return getAccountTemplate().getAccount(String.valueOf(accountId));
    }

    /**
     * 判断当前用户是否企业用户
     */
    protected final boolean isCorpAccount(HttpServletRequest request) {
        Account account = getCurrentAccount(request);
        return Constant.ACCOUNT_TYPE_CORPORATION.equals(account
                .getAccountType());
    }

    protected final FeeRatioInterf getFeeRatioService() {
        return (FeeRatioInterf) IPBMgrFactory
                .getMgr(ForeDict.SERVICE_FEE_RATIO);
    }

    protected final IMySpaceService getMySpaceService() {
        return (IMySpaceService) IPBAppFactory
                .getObj(ForeDict.SERVICE_MY_SPACE);
    }

    protected final TransactionTemplate getTransactionTemplate() {
        return (TransactionTemplate) IPBAppFactory
                .getObj(ForeDict.TRANSACTION_TEMPLATE);
    }

    /**
     * 加载子账户列表
     */
    private void loadSubAccountList(HttpServletRequest request) {
        PermissionService permissionService = PermissionService
                .getPermissionService();
        Account account = getCurrentAccount(request);
        SubAccount defaultSubAccount = account.getDefaultSubAccount();
        if (!permissionService.isCorpOperator(request)) { // 个人用户
            // 获取当前个人用户的所有子账户列表
            Set subAccounts = account.getSubAccounts();
            request.setAttribute("subAccounts", subAccounts);
        } else { // 企业操作员
            // 获取当前企业操作员具有充值权限的子账户列表
            List subAccounts = permissionService.getSubAccounts(request,
                    Constant.PERMIS_TYPE_BANKDEPOSIT, defaultSubAccount);
            request.setAttribute("subAccounts", subAccounts);
        }
    }

    /**
     * 准备初始化数据
     */
    public ActionForward prepare(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 判断当前用户是否具有充值权限
        PermissionService permissionService = PermissionService
                .getPermissionService();
        if (!permissionService.hasPermission(request,
                Constant.PERMIS_TYPE_BANKDEPOSIT)) {
            handleAppException(mapping, actionForm, request, response,
                    TransactionException.NO_PERMISSION);
        }
        loadSubAccountList(request);
        // 默认选择默认子账户
        InpourForm form = (InpourForm) actionForm;
        String subAccountId = form.getSubAccountId();
        if (subAccountId == null || subAccountId.length() == 0) {
            Account account = getCurrentAccount(request);
            SubAccount defaultSubAccount = account.getDefaultSubAccount();
            form.setSubAccountId(defaultSubAccount.getAccountId());
        }
        // 设置交易类型
        form.setActionType(getActionTypeCode(request));
        loadIsCorpAccount(request);
        return mapping.findForward(ForeDict.FORWARD_STEP_1);
    }

    /**
     * 校验金额的格式和数值
     * 
     * @param amountValue
     *            字符串型金额值
     * @return Double型金额值
     * @throws TransactionException
     *             如果金额格式错误或金额值小于等于0
     */
    protected Double validateAmount(String amountValue)
            throws TransactionException {
        try {
            Double amount = new Double(amountValue);
            if (amount.doubleValue() <= 0) {
                throw TransactionException.INVALID_AMOUT;
            }
            return amount;
        } catch (NumberFormatException e) {
            throw TransactionException.INVALID_AMOUT;
        }
    }

    /**
     * 计算实际的充值金额
     */
    protected final Double getActualInpourAmount(Transaction trans) {
        double inpourAmount = trans.getAmount().doubleValue();
        double inpourFee = trans.getCreditFee().doubleValue();
        return new Double((inpourAmount - inpourFee));
    }

}
